#ifndef EFFECT_H
#define EFFECT_H

#include "Resource.h"
#include "BaseTexture.h"
#include "Vector4.h"
#include "Matrix.h"
#include "EffectParams.h"
#include "CommonTypes.h"

namespace Cvekas {

/// Manages device render states and shader parameters
class Effect : public Resource
{
public:
	/// Constructor. Loads effect from file.
	Effect(ResourceId id, D3DDevicePtr device, const std::string& name, const std::string& filename);

	/*
	/// Constructor. Loads effect from in-memory string.
	Effect(ResourceId id, DevicePtr _device, const std::string& name, const char* effect);
	*/

	/// Destructor
	~Effect();

	/// Finds parameter by its name
	/// \param name Parameter name
	/// \returns Paramter handle, or NULL if such name does not exist
	ParamHandle getParamByName(const std::string& name);

	/// Finds parameter by its semantic
	/// \param name Parameter semantic
	/// \returns Parameter handle, or NULL if such semantic does not exist
	ParamHandle getParamBySemantic(const std::string& name);

	/// Sets bool parameter
	void setParamValue(ParamHandle handle, bool value);
	/// Sets float parameter
	void setParamValue(ParamHandle handle, float value);
	/// Sets int parameter
	void setParamValue(ParamHandle handle, int value);
	/// Sets Matrix parameter
	void setParamValue(ParamHandle handle, const Matrix& value);
	/// Sets Texture parameter
	void setParamValue(ParamHandle handle, TexturePtr texture);
	/// Sets Vector4 parameter
	void setParamValue(ParamHandle handle, const Vector4& value);
	/// Sets arbitrary type parameter
	void setParamValue(ParamHandle handle, const void* ptr, uint size);

	/// Begins rendering with this effect
	/// \returns Number of passes this effect has
	unsigned int begin();

	/// Ends rendering with this effect
	void end();

	/// Begins pass
	/// \param pass Pass number, must be less than number renturned by begin()
	void beginPass(uint pass);

	/// Ends pass
	void endPass();

	/// Sets technique with specified index. Technique 0 is used by default
	void setTechnique(uint index);

	/// Updates effect parameters between beginPass and endPass calls.
	/// Must be called before rendering every object if more than one object is rendered per pass.
	void commitChanges();

	/// Applies automatically handled parameters
	void applyAutoParams();

	EffectParamsPtr getAutoParams() { return auto_params; };

	/// Returns pointer to ID3DXEffect stored in this %Effect
	ID3DXEffect* getD3DXEffect();

	/// You shouldn't call this
	void onDeviceLost();
	/// You shouldn't call this
	void onDeviceReset();

	static const uint INVALID_PASS = 0xFFFFFFFF;
	static const uint INVALID_TECHNIQUE = 0xFFFFFFFF;

private:
	void setUpAutoParams();

	ID3DXEffect* effect;
	EffectParamsPtr auto_params;
	D3DDevicePtr device;
};

typedef boost::shared_ptr<Effect> EffectPtr;

} // namespace

#endif